package com.andox.fn.inf.rpc.rest.protocol;

import java.util.List;

import org.apache.commons.lang3.StringUtils;

import com.andox.fn.inf.rpc.rest.config.InterfaceConfig;
import com.andox.fn.inf.rpc.rest.config.ReferenceConfig;
import com.andox.fn.inf.rpc.rest.extension.ExtensionLoader;
import com.andox.fn.inf.rpc.rest.extension.ObjectFactory;
import com.andox.fn.inf.rpc.rest.filter.Filter;
import com.andox.fn.inf.rpc.rest.filter.FilterObjectFactory;
import com.andox.fn.inf.rpc.rest.filter.FilterUtil;
import com.andox.fn.inf.rpc.rest.filter.Invoker;
import com.andox.fn.inf.rpc.rest.protocol.registry.RegistryProtocol;
import com.google.common.collect.Lists;


public class ProtocolObjectFactory extends ObjectFactory<Protocol>{
	
	public static final String REST_CONTROLLER = "restcontroller";
	public static final String REGISTRY = "registry";
	
	@Override
	public Protocol getDefault() {
		return this.table.get("restcontroller");
	}
	
	@Override
	protected void init() {
		FilterProtocol fp = new FilterProtocol(new RestControllerProtocol());
		this.table.put("registry", new RegistryProtocol());
		this.table.put("restcontroller", fp);
	}
	
	static class FilterProtocol implements Protocol{
		private Protocol protocol;
		
		public FilterProtocol(Protocol real) {
			protocol = real;
		}
		
		@Override
		public Invoker refer(ReferenceConfig referenceConfig) {
			if (protocol.getClass().equals(RegistryProtocol.class)) {
				return protocol.refer(referenceConfig);
			}
			
			Invoker invoker = protocol.refer(referenceConfig);
			
			invoker = buildFilter(invoker, referenceConfig, Lists.newArrayList());
			
			return invoker;
		}

		@Override
		public Invoker export(Invoker invoker) {
			if (protocol.getClass().equals(RegistryProtocol.class)) {
				return protocol.export(invoker);
			}
			Invoker tmp = invoker;
			tmp = buildFilter(tmp, tmp.getConfig(), Lists.newArrayList(FilterObjectFactory.EXCLUDE));
			tmp = protocol.export(tmp);
			
			return tmp;
		}
		
		private Invoker buildFilter(Invoker invoker, InterfaceConfig ic, List<String> includeFilter) {
			String filterString = ic.getFilter();
			String[] filterStringArray = StringUtils.split(filterString, ",");
			
			List<Filter> filters = Lists.newArrayList();
			for (String f : filterStringArray) {
				Filter filter = ExtensionLoader.getExtensionLoader(Filter.class).getExtension(f);
				filters.add(filter);
			}
			
			for (String f : includeFilter) {
				Filter filter = ExtensionLoader.getExtensionLoader(Filter.class).getExtension(f);
				filters.add(filter);
			}
			
			Invoker filterInvoker = FilterUtil.buildFilter(invoker, filters);
			
			return filterInvoker;
		}
	}
}